package clientN

import (
	"bufio"
	"fmt"
	"log"
	"net"
	"sync"
	"wxp2p/common"
)

// 远程连接<-->local:2222<-->client_client<-->webrtcdatachannel<-->server_client<-->local:3389

type TCPClient struct {
	id_conn_map_nutex sync.RWMutex
	id_conn_map       map[string]net.Conn
	port              string
	host              string
	dataChannel       *WebrtcOffer
	listener          *net.Listener
}

func NewTCPClient(host string, port string, dc *WebrtcOffer) *TCPClient {
	tc := TCPClient{host: host, port: port, dataChannel: dc}
	tc.id_conn_map = make(map[string]net.Conn)
	tc.id_conn_map_nutex = sync.RWMutex{}
	return &tc
}

// client-client监听，接收新连接
func (tc *TCPClient) ListenLocalTCP() {
	listen, err := net.Listen("tcp", tc.host+":"+tc.port)
	if err != nil {
		fmt.Println("listen error: ", err)
		return
	}
	tc.listener = &listen
	for {
		//一次请求，另一个client就得dial一次，所以data channel不能只传输数据，还得传输命令，两边得定义规则识别每次accept,需要把接收到的数据对应发送到客户端
		conn, err := listen.Accept() //2222
		if err != nil {
			fmt.Println("accept error: ", err)
			break
		}
		log.Println("new conn:", conn.RemoteAddr().String())
		connId := conn.RemoteAddr().String()
		tc.id_conn_map_nutex.Lock()
		tc.id_conn_map[connId] = conn
		tc.id_conn_map_nutex.Unlock()
		tc.dataChannel.DataSendChan <- common.PackageData(connId, "new", "-")
		// read
		go func() {
			defer func() {
				conn.Close()
				tc.id_conn_map_nutex.Lock()
				delete(tc.id_conn_map, connId)
				tc.id_conn_map_nutex.Unlock()
				tc.dataChannel.DataSendChan <- common.PackageData(connId, "close", "-")
			}()
			if conn == nil {
				log.Panic("无效的 socket 连接")
			}
			buf := make([]byte, 60535)
			reader := bufio.NewReader(conn)
			for {
				cnt, err := reader.Read(buf)
				if cnt == 0 || err != nil {
					// conn.Close()
					break
				}
				tc.dataChannel.DataSendChan <- common.PackageData(connId, "data", string(buf[0:cnt]))
			}
		}()
	}
}
func (tc *TCPClient) StopListen() {
	(*tc.listener).Close()
}
func (tc *TCPClient) RecDataHandler(buf []byte) {
	id, action, content := common.UnPackageData(buf)
	switch action {
	case "data":
		tc.id_conn_map_nutex.RLock()
		conn, bHave := tc.id_conn_map[id]
		tc.id_conn_map_nutex.RUnlock()
		if bHave {
			_, err := conn.Write([]byte(content))
			if err != nil {
				log.Println(err)
				tc.id_conn_map_nutex.Lock()
				delete(tc.id_conn_map, id)
				tc.id_conn_map_nutex.Unlock()
				tc.dataChannel.DataSendChan <- common.PackageData(id, "close", "")
			}
		} else {
			log.Println("3.出错了，应该存在的连接失败了")
		}
	case "close":
		tc.id_conn_map_nutex.RLock()
		conn, bHave := tc.id_conn_map[id]
		tc.id_conn_map_nutex.RUnlock()
		if bHave {
			conn.Close()
			tc.id_conn_map_nutex.Lock()
			delete(tc.id_conn_map, id)
			tc.id_conn_map_nutex.Unlock()
		}
	}
}
